package com.itic.appbase.framework.utils.wxpay;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itic.appbase.framework.utils.DateHelper;
import com.itic.appbase.framework.utils.IdGen;
import com.itic.appbase.framework.utils.IpAddressHelper;
import com.itic.appbase.framework.utils.MD5Helper;
import com.itic.appbase.framework.utils.NumberStringHelper;
import com.itic.appbase.framework.utils.StringHelper;
import com.itic.appbase.framework.utils.XmltoJsonUtil;
import com.itic.appbase.framework.utils.wxpay.vo.PayMsgVo;
import com.itic.appbase.framework.utils.wxpay.vo.PaySuccessVo;
import com.itic.appbase.framework.utils.wxpay.vo.WxpayConfig;

import net.sf.json.JSONObject;

  
public class WeixinPayUtil {
	
	 
	
	public static PaySuccessVo success( HttpServletRequest request, HttpServletResponse response ) throws Exception { 
		PaySuccessVo paySuccessVo = new PaySuccessVo();
		String orderNum = "999999999";
		String payTime = null;
		String payNo = null;
		request.setCharacterEncoding("UTF-8");  
	    response.setCharacterEncoding("UTF-8");  
	    response.setContentType("text/html;charset=UTF-8");  
	    response.setHeader("Access-Control-Allow-Origin", "*");   
	    InputStream in=request.getInputStream();  
	    ByteArrayOutputStream out=new ByteArrayOutputStream();  
	    byte[] buffer =new byte[1024];  
	    int len=0;  
	    while((len=in.read(buffer))!=-1){  
	        out.write(buffer, 0, len);  
	    }  
	    out.close();  
	    in.close();  
	    String msgxml=new String(out.toByteArray(),"utf-8");//xml数据  
	    System.out.println(msgxml); 
	    String xml2json = XmltoJsonUtil.xml2JSON(msgxml);
	    
	    JSONObject fromObject = JSONObject.fromObject(xml2json);
		JSONObject jsonObject = fromObject.getJSONObject("xml");
		
		 String result_code = jsonObject.getJSONArray("result_code").get(0).toString();
		 String return_code = jsonObject.getJSONArray("return_code").get(0).toString();
		 
		 if( result_code.equals("SUCCESS") && return_code.equals("SUCCESS") ){ 
			 
				/*这里没有测试成功，需要进一步研究的，回调验证
				 *  String appid  = jsonObject.getJSONArray("appid").get(0).toString();  
				 String back_type  = jsonObject.getJSONArray("bank_type").get(0).toString();  
				 String cash_fee  = jsonObject.getJSONArray("cash_fee").get(0).toString();  
				 String fee_type  = jsonObject.getJSONArray("fee_type").get(0).toString();  
				 String is_subscribe  = jsonObject.getJSONArray("is_subscribe").get(0).toString();  
				 String mch_id  = jsonObject.getJSONArray("mch_id").get(0).toString();  
				 String nonce_str  = jsonObject.getJSONArray("nonce_str").get(0).toString();  
				 String openid  = jsonObject.getJSONArray("openid").get(0).toString();  
				 
				 //String out_trade_no  = jsonObject.get("out_trade_no").toString();  
				 String sign  = jsonObject.getJSONArray("sign").get(0).toString();  
				 String time_end  = jsonObject.getJSONArray("time_end").get(0).toString();  
				 String total_fee  = jsonObject.getJSONArray("total_fee").get(0).toString();  
				 String trade_type  = jsonObject.getJSONArray("trade_type").get(0).toString();  
				 String transaction_id  = jsonObject.getJSONArray("transaction_id").get(0).toString(); 
				 
				 //生成签名
				 SortedMap<Object,Object> parameters = new TreeMap<Object,Object>(); 
				 parameters.put("appid", appid);
				 parameters.put("back_type", back_type);
				 parameters.put("cash_fee", cash_fee);
				 parameters.put("fee_type", fee_type);
				 parameters.put("is_subscribe", is_subscribe);
				 parameters.put("mch_id", mch_id);
				 parameters.put("nonce_str", nonce_str);
				 parameters.put("openid", openid);
				 parameters.put("out_trade_no", out_trade_no);
				 parameters.put("time_end", time_end);
				 parameters.put("total_fee", total_fee);
				 parameters.put("trade_type", trade_type);
				 parameters.put("transaction_id", transaction_id);
				 parameters.put("result_code", result_code);
				 parameters.put("return_code", return_code);
				
				 WeixinpayConfig weixinpayConfig = new WeixinpayConfig();
				 String sign2 = createSign("UTF-8",weixinpayConfig.getSecret(),parameters);
				 if( sign.equals(sign2) ){
					  
				 }*/
			 
			 
			     //处理自己的业务逻辑  
			     orderNum  = jsonObject.getJSONArray("out_trade_no").get(0).toString(); 
			     payTime = jsonObject.getJSONArray("time_end").get(0).toString();
			     payNo = jsonObject.getJSONArray("transaction_id").get(0).toString();
			     paySuccessVo.setOrderNo(orderNum);
			     paySuccessVo.setPayNo(payNo);
			     paySuccessVo.setPayTime(payTime);
			 
		 }
		 return paySuccessVo;
	}
	
	/**
	 * 微信支付工具类
	 * @param request
	 * @param weixinpayConfig
	 * @param vo
	 * @return
	 */
	public static  Map<String, Object> pay(HttpServletRequest request,WxpayConfig weixinpayConfig, PayMsgVo vo) { 
		
		DataInputStream input = null;   
		  
		java.io.ByteArrayOutputStream out = null;   
		
		try{
			  //订单支付备注
		    // String body = "用户购买"+order.getTotalProduct()+"件商品，共消费"+order.getTotalMoney()+"元！";
		    //Wxpay weixinpayConfig = getWxpayConfig();
		    String remortIP = IpAddressHelper.getRemortIP4();
		    String nonceStr = IdGen.uuid();
		    String money="1";
		    //如果是测试环境，则使用0.01元
			//String valueByKey = sysSettingService.getByKey("WXPAY_IS_OPEN_TEST");
			if( StringHelper.isNoneBlank(weixinpayConfig.getIsTest()) && "open".equals(weixinpayConfig.getIsTest()) ){
				money = "1";
			}else{
				money = NumberStringHelper.mulString(vo.getTotalMoney(), "100");
				//money = totalMoney;
			}
		    
		    SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();  
	        parameters.put("appid", weixinpayConfig.getAppid());  
	        parameters.put("mch_id", weixinpayConfig.getMchId());  
	        //parameters.put("device_info", "1000");  
	        parameters.put("body", vo.getDesc());  
	        parameters.put("nonce_str", nonceStr);  
	        parameters.put("notify_url", weixinpayConfig.getNotifyUrl());
	        parameters.put("out_trade_no", vo.getOrderNum());
	        parameters.put("spbill_create_ip", remortIP);
	        parameters.put("total_fee", money);
	        parameters.put("trade_type", "APP");
	        
		    
		    String sign = createSign("UTF-8",weixinpayConfig.getSecret(),parameters);
		    
		    StringBuilder sb = new StringBuilder();  
		    
	        sb.append("<xml>");  
	        sb.append("<appid>"+weixinpayConfig.getAppid()+"</appid>");  
	        sb.append("<mch_id>"+weixinpayConfig.getMchId()+"</mch_id>");  
	        //sb.append("<device_info>1000</device_info>");  
	        sb.append("<body>"+vo.getDesc()+"</body>");  
	        sb.append("<nonce_str>"+nonceStr+"</nonce_str>");  
	        sb.append("<notify_url>"+weixinpayConfig.getNotifyUrl()+"</notify_url>");  
	        sb.append("<out_trade_no>"+vo.getOrderNum()+"</out_trade_no>");  
	        sb.append("<spbill_create_ip>"+remortIP+"</spbill_create_ip>");  
	        sb.append("<total_fee>"+money+"</total_fee>");  
	        sb.append("<trade_type>APP</trade_type>");  
	        sb.append("<sign>"+sign+"</sign>");  
	        sb.append("</xml>"); 
	        
	        String paramXml = sb.toString();
	        		
	        byte[] xmlData = paramXml.getBytes(); 
			
			
			URL url = new URL(weixinpayConfig.getWxurl());
			URLConnection urlCon = url.openConnection();   
			  
	        urlCon.setDoOutput(true);   
	  
	        urlCon.setDoInput(true);   
	  
	        urlCon.setUseCaches(false);   
	        
	        //将xml数据发送到位置服务   
	        
	        urlCon.setRequestProperty("Content-Type", "text/xml");   
	  
	        urlCon.setRequestProperty("Content-length",String.valueOf(xmlData.length));   
	  
	        DataOutputStream printout = new DataOutputStream(urlCon.getOutputStream());   
	  
	        printout.write(xmlData);   
	  
	        printout.flush();   
	  
	        printout.close();   
	  
	        input = new DataInputStream(urlCon.getInputStream());   
	  
	       @SuppressWarnings("unused")
		   byte[] rResult;   
	  
	        out = new java.io.ByteArrayOutputStream();   
	  
	       byte[] bufferByte = new byte[256];   
	  
	       int l = -1;   
	  
	       @SuppressWarnings("unused")
		   int downloadSize = 0;   
	  
	       while ((l = input.read(bufferByte)) > -1) {   
	  
	            downloadSize += l;   
	  
	            out.write(bufferByte, 0, l);   
	  
	            out.flush();   
	  
	        }   
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( null != input ){
				try {
					input.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if( null != out ){
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
  
        String string = out.toString();
        Map<String, Object> jsonPay = getJsonPay(weixinpayConfig,string);
        return jsonPay;
    }  
	
	
      
	public static void back(HttpServletRequest request,WxpayConfig weixinpayConfig, PayMsgVo vo) { 
		
	}
	
	
	public static Map<String,Object> getJsonPay(WxpayConfig weixinpayConfig,String xml){
		HashMap<String, Object> result = new HashMap<String,Object>();
		if( StringHelper.isNotBlank(xml) ){
			String date = DateHelper.getDate("MMddhhmmss");
			//WeixinpayConfig weixinpayConfig = new WeixinpayConfig();
			//Wxpay weixinpayConfig = getWxpayConfig();
			String xml2json = XmltoJsonUtil.xml2JSON(xml);
			JSONObject fromObject = JSONObject.fromObject(xml2json);
			JSONObject jsonObject = fromObject.getJSONObject("xml");
			
			
			
			Object nonce_str = jsonObject.getJSONArray("nonce_str").get(0);
			result.put("nonce_str", nonce_str.toString());
			
			//Object device_info = jsonObject.getJSONArray("device_info").get(0);
			//result.put("device_info", device_info.toString());
			
			Object appid = jsonObject.getJSONArray("appid").get(0);
			result.put("appid", appid.toString());
			
			Object sign = jsonObject.getJSONArray("sign").get(0);
			result.put("sign", sign.toString());
			
			Object trade_type = jsonObject.getJSONArray("trade_type").get(0);
			result.put("trade_type", trade_type.toString());
			
			Object mch_id = jsonObject.getJSONArray("mch_id").get(0);
			result.put("mch_id", mch_id.toString());
			
			Object prepay_id = jsonObject.getJSONArray("prepay_id").get(0);
			result.put("prepay_id", prepay_id.toString());
			
			result.put("timestamp", date);
			
			SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();  
			parameters.put("appid",appid.toString());
			parameters.put("partnerid", mch_id.toString());
			parameters.put("prepayid", prepay_id.toString());
			parameters.put("package", "Sign=WXPay");
			parameters.put("noncestr", nonce_str.toString());
			parameters.put("timestamp", date);
			
			String sign2 = createSign("MD5",weixinpayConfig.getSecret(),parameters);
			result.put("sign", sign2);
		}
		
		return result;
	}
	
	
	/** 
     * 微信支付签名算法sign 
     * @param characterEncoding 
     * @param parameters 
     * @return 
     */  
    @SuppressWarnings("rawtypes")
	public static String createSign(String characterEncoding,String key,SortedMap<Object,Object> parameters){  
        StringBuffer sb = new StringBuffer();  
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）  
        Iterator it = es.iterator();  
        while(it.hasNext()) {  
            Map.Entry entry = (Map.Entry)it.next();  
            String k = (String)entry.getKey();  
            Object v = entry.getValue();  
            if(null != v && !"".equals(v)   
                    && !"sign".equals(k) && !"key".equals(k)) {  
                sb.append(k + "=" + v + "&");  
            }  
        }  
        sb.append("key=" + key);  
        String sign = MD5Helper.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  
        return sign;  
    }  
	
	
	public Map<String,String> getParamMap(HttpServletRequest request){
		Map<String,String> params = new HashMap<String,String>();
		Map<String,String[]> requestParams = request.getParameterMap();
		if( null != requestParams ){
			for( Iterator<String> iter = requestParams.keySet().iterator();iter.hasNext();){
				String name = (String)iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for( int i=0;i<values.length;i++){
					valueStr=(i==values.length-1)?valueStr+values[i]:valueStr+values[i]+",";
				}
				//乱码解决，这段代码再出现乱码时使用。如果masign和sign不相等也可以使用这段代码
				//valueStr=new String(valueStr.getBytes("ISO-8859-1"),"gbk");
				params.put(name,valueStr);
				
			}
		}
		return params;
	}
	
	
	public static String setXml(String return_code,String return_msg){  
        return "<xml><return_code><![CDATA["+return_code+"]]></return_code><return_msg><![CDATA["+return_msg+"]]></return_msg></xml>";  
    } 
}
